home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 38 / Amiga Format CD38 (1999-03-15)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-04].iso / -seriously_amiga- / programming / other / cyberxxxsrc / decoder / txt / decodemsadpcm.c < prev    next >
C/C++ Source or Header  |  1999-02-08  |  5KB  |  222 lines

  1. /*
  2. sc:c/sc opt txt/DecodeMSADPCM.c
  3. */
  4.  
  5. #include "Decode.h"
  6.  
  7. #define MSADPCM_NUM_COEF        (7)
  8. #define MSADPCM_MAX_CHANNELS    (2)
  9.  
  10. #define MSADPCM_CSCALE          (8)
  11. #define MSADPCM_PSCALE          (8)
  12. #define MSADPCM_CSCALE_NUM      (1 << MSADPCM_CSCALE)
  13. #define MSADPCM_PSCALE_NUM      (1 << MSADPCM_PSCALE)
  14.  
  15. #define MSADPCM_DELTA4_MIN      (16)
  16.  
  17. #define MSADPCM_OUTPUT4_MAX     (7)
  18. #define MSADPCM_OUTPUT4_MIN     (-8)
  19.  
  20. #define bBitsPerSample 8
  21. #define bPredictors 7
  22. #define wBlockHeaderBytes 7
  23.  
  24. struct MSADPCMData {
  25.   short samplesPerBlock;
  26. };
  27.  
  28. short gaiP4[]={
  29.   230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230
  30. };
  31.  
  32. short gaiCoef1[]={
  33.   256, 512,   0, 192, 240, 460, 392
  34. };
  35.  
  36. short gaiCoef2[]={
  37.     0,-256,  0,   64,   0,-208,-232
  38. };
  39.  
  40. /* /// "DecodeMSADPCMMono()" */
  41. __asm ulong DecodeMSADPCMMono(REG(a0) uchar *from,
  42.                               REG(a1) short *toL,
  43.                               REG(a2) short *toR,
  44.                               REG(d0) ulong size,
  45.                               REG(a3) struct MSADPCMData *spec)
  46. {
  47.   short wSamplesPerBlock;
  48.   ulong dwTotalPos, dwDecoded, dwSrcLen;
  49.  
  50.   wSamplesPerBlock=spec->samplesPerBlock;
  51.   dwDecoded=0;
  52.   dwTotalPos=0;
  53.   dwSrcLen=size;
  54.  
  55.   while (dwTotalPos<dwSrcLen) {
  56.     short n;
  57.     short aiSamp1, aiSamp2;
  58.     short aiCoef1, aiCoef2;
  59.     short aiDelta;
  60.     long  lSamp, lPrediction;
  61.     short iInput, iNextInput;
  62.     short iFirstNibble, iDelta;
  63.     uchar bPredictor;
  64.  
  65.     dwTotalPos+=wBlockHeaderBytes;
  66.     if (dwTotalPos>dwSrcLen) goto adpcmDecode4BitExit;
  67.  
  68.     bPredictor=*from++;
  69.     if (bPredictor>=bPredictors) {
  70.       dwDecoded=0;
  71.       goto adpcmDecode4BitExit;
  72.     }
  73.     aiCoef1=gaiCoef1[bPredictor];
  74.     aiCoef2=gaiCoef2[bPredictor];
  75.     aiDelta=get16pc(from);
  76.     aiSamp1=get16pc(from);
  77.     aiSamp2=get16pc(from);
  78.  
  79.     *toL++=aiSamp2;
  80.     *toL++=aiSamp1;
  81.  
  82.     dwDecoded+=2;
  83.         
  84.     iFirstNibble=1;
  85.     for (n=2; n<wSamplesPerBlock; n++) {
  86.       char hiNibble,loNibble;
  87.  
  88.       if (iFirstNibble) {
  89.         dwTotalPos++;
  90.         if (dwTotalPos>dwSrcLen) goto adpcmDecode4BitExit;
  91.         hiNibble=(*from) & 240;
  92.         loNibble=(*from) << 4;
  93.         iNextInput=((short)loNibble)/16;
  94.         iInput=((short)hiNibble)/16;
  95.         from++;
  96.         iFirstNibble=0;
  97.       } else {
  98.         iInput=iNextInput;
  99.         iFirstNibble=1;
  100.       }
  101.  
  102.       iDelta=aiDelta;
  103.       aiDelta=(short)((gaiP4[iInput & 15] * (long)iDelta) >> MSADPCM_PSCALE);
  104.       if (aiDelta<MSADPCM_DELTA4_MIN) aiDelta=MSADPCM_DELTA4_MIN;
  105.  
  106.       lPrediction=(((long)aiSamp1*aiCoef1)+((long)aiSamp2*aiCoef2)) >> MSADPCM_CSCALE;
  107.       lSamp=((long)iInput*iDelta)+lPrediction;
  108.  
  109.       if (lSamp>32767)
  110.         lSamp=32767;
  111.       else
  112.         if (lSamp<-32768) lSamp=-32768;
  113.  
  114.       *toL++=lSamp;
  115.  
  116.       aiSamp2=aiSamp1;
  117.       aiSamp1=(short)lSamp;
  118.       dwDecoded++;
  119.     }
  120.   }
  121.   adpcmDecode4BitExit:
  122.   return dwDecoded;
  123. }
  124. /* \\\ */
  125.  
  126. /* /// "DecodeMSADPCMStereo()" */
  127. __asm ulong DecodeMSADPCMStereo(REG(a0) uchar *from,
  128.                                 REG(a1) ushort *toL,
  129.                                 REG(a2) ushort *toR,
  130.                                 REG(d0) ulong size,
  131.                                 REG(a3) struct MSADPCMData *spec)
  132. {
  133.   short wSamplesPerBlock;
  134.   ulong dwTotalPos,dwDecoded,dwSrcLen;
  135.  
  136.   wSamplesPerBlock=spec->samplesPerBlock;
  137.   dwDecoded=0;
  138.   dwTotalPos=0;
  139.   dwSrcLen=size;
  140.  
  141.   while (dwTotalPos<dwSrcLen) {
  142.     short n;
  143.     short aiSamp1[2], aiSamp2[2];
  144.     short aiCoef1[2], aiCoef2[2];
  145.     short aiDelta[2];
  146.     long  lSamp, lPrediction;
  147.     short iInput, iNextInput;
  148.     short iFirstNibble, iDelta;
  149.     uchar bPredictor;
  150.     ulong cnt;
  151.  
  152.     dwTotalPos+=wBlockHeaderBytes;
  153.     if (dwTotalPos>dwSrcLen) goto adpcmDecode4BitExit;
  154.  
  155.     for (cnt=0; cnt<2; cnt++) {
  156.       bPredictor=*from++;
  157.       if (bPredictor>=bPredictors) {
  158.         dwDecoded=0;
  159.         goto adpcmDecode4BitExit;
  160.       }
  161.       aiCoef1[cnt]=gaiCoef1[bPredictor];
  162.       aiCoef2[cnt]=gaiCoef2[bPredictor];
  163.     }
  164.     for (cnt=0; cnt<2; cnt++) aiDelta[cnt]=get16pc(from);
  165.     for (cnt=0; cnt<2; cnt++) aiSamp1[cnt]=get16pc(from);
  166.     for (cnt=0; cnt<2; cnt++) aiSamp2[cnt]=get16pc(from);
  167.  
  168.     *toL++=aiSamp2[0];
  169.     *toL++=aiSamp1[0];
  170.     *toR++=aiSamp2[1];
  171.     *toR++=aiSamp1[1];
  172.  
  173.     dwDecoded+=2;
  174.  
  175.     iFirstNibble=1;
  176.     for (n=2; n<wSamplesPerBlock; n++) {
  177.       char hiNibble,loNibble;
  178.  
  179.       for (cnt=0; cnt<2; cnt++) {
  180.         if (iFirstNibble) {
  181.           dwTotalPos++;
  182.           if (dwTotalPos>dwSrcLen) goto adpcmDecode4BitExit;
  183.           hiNibble=(*from) & 240;
  184.           loNibble=(*from) << 4;
  185.           iNextInput=((short)loNibble)/16;
  186.           iInput=((short)hiNibble)/16;
  187.           from++;
  188.           iFirstNibble=0;
  189.         } else {
  190.           iInput=iNextInput;
  191.           iFirstNibble=1;
  192.         }
  193.  
  194.         iDelta=aiDelta[cnt];
  195.         aiDelta[cnt]=(short)((gaiP4[iInput & 15] * (long)iDelta) >> MSADPCM_PSCALE);
  196.         if (aiDelta[cnt]<MSADPCM_DELTA4_MIN) aiDelta[cnt]=MSADPCM_DELTA4_MIN;
  197.  
  198.         lPrediction=(((long)aiSamp1[cnt]*aiCoef1[cnt])+((long)aiSamp2[cnt]*aiCoef2[cnt])) >> MSADPCM_CSCALE;
  199.         lSamp=((long)iInput*iDelta)+lPrediction;
  200.  
  201.         if (lSamp>32767)
  202.           lSamp=32767;
  203.         else
  204.           if (lSamp<-32768) lSamp=-32768;
  205.  
  206.         if (cnt==0)
  207.           *toL++=lSamp;
  208.         else
  209.           *toR++=lSamp;
  210.  
  211.         aiSamp2[cnt]=aiSamp1[cnt];
  212.         aiSamp1[cnt]=(short)lSamp;
  213.       }
  214.       dwDecoded++;
  215.     }
  216.   }
  217.   adpcmDecode4BitExit:
  218.   return dwDecoded;
  219. }
  220. /* \\\ */
  221.  
  222.